package com.lock.immersive.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceApacheHttpImpl;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.lock.immersive.config.MyWxPayConfig;
import com.lock.immersive.exception.BusinessException;
import com.lock.immersive.mapper.*;
import com.lock.immersive.pojo.domain.*;
import com.lock.immersive.pojo.dto.OrderDetail;
import com.lock.immersive.pojo.enums.OrderStatus;
import com.lock.immersive.pojo.enums.ProductType;
import com.lock.immersive.pojo.enums.TuanProcess;
import com.lock.immersive.pojo.vo.WxPayment;
import com.lock.immersive.service.OrdersService;
import com.lock.immersive.utils.ErrorCode;
import com.lock.immersive.utils.JWT;
import com.lock.immersive.utils.Md5Utils;
import com.lock.immersive.utils.ResponseApi;
import me.chanjar.weixin.common.service.WxService;
import org.apache.catalina.connector.Response;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author zhao
 * @description 针对表【orders】的数据库操作Service实现
 * @createDate 2023-07-02 00:04:03
 */
@Service
@Transactional
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders>
        implements OrdersService {
    @Resource
    private AddressMapper addressMapper;
    @Resource
    public OrdersMapper ordersMapper;
    @Resource
    public ProductMapper productMapper;
    @Resource
    public ProductItemMapper productItemMapper;
    @Resource
    public UserMapper userMapper;
    @Resource
    public TuanMapper tuanMapper;
    @Resource
    public UserCouponMapper userCouponMapper;
    @Resource
    public UserTuanMapper userTuanMapper;
    @Resource
    public CouponMapper couponMapper;
    @Value("${wx.pay.appId}")
    public String appId;
    @Value("${wx.pay.mchKey}")
    public String mchKey;
    @Value("${wx.pay.mchId}")
    public String mchId;
    @Autowired
    private WxPayService wxService;

    public String customFormatDate(String dateFormat) {
        SimpleDateFormat simpleDateFormat;
        simpleDateFormat = new SimpleDateFormat(dateFormat);
        Date date = new Date();
        String str = simpleDateFormat.format(date);
        return str;
    }

    @Override
    public ResponseApi<WxPayment> wxUnifiedOrder(OrderDetail detail, HttpServletRequest request) throws Exception {
        //0.判断是否可以购买
        String userId = JWT.getTokenId(request.getHeader("token"));

        UserTuan userTuan = userTuanMapper.selectById(detail.getUserTuanId());
        Tuan tuan = tuanMapper.selectById(userTuan.getTuanId());
        if (tuan.getTuanProcess().equals(userTuan.getTuanProcess())) {
            throw new BusinessException(ErrorCode.DONNOT_REPEAT);        }
        if (!tuan.getTuanProcess().equals(userTuan.getNextTuanProcess())) {
            throw new BusinessException(ErrorCode.PLEASE_WAIT);
        }
        Integer merchantId = userTuan.getMerchantId();
        Integer productId = userTuan.getProductId();
        Integer productItemId = userTuan.getProductItemId();
        Integer addressId = detail.getAddressId();
        Address address = addressMapper.selectById(addressId);
        ProductItem productItem = productItemMapper.selectById(productItemId);
        Product product = productMapper.selectById(productId);
        Double uniPrice = productItem.getItemPrice();
        Double postFee = product.getPostFee();
        Double totalPrice = uniPrice * detail.getCounts() + postFee;
        if (Objects.isNull(address)) {
            throw new BusinessException(ErrorCode.INVALID_ADDRESS);
        }
        Double couponPrice = 0.00;
        if (StrUtil.isNotBlank(detail.getUserCouponId() + "")) {
            Integer userCouponId = detail.getUserCouponId();
            UserCoupon userCoupon = userCouponMapper.selectById(userCouponId);
            if (userCoupon == null) {
                throw new BusinessException(ErrorCode.DONNOT_HAVE_COUPON);
            }
            Coupon coupon = couponMapper.selectById(userCoupon.getCouponId());
            if (userCoupon.getIsUsed() == 1) {
                throw new BusinessException(ErrorCode.COUPON_BEEN_USED);
            }
            if (StrUtil.isNotBlank(coupon.getTuanId() + "") && !coupon.getTuanId().equals(tuan.getTuanId())) {
                throw new BusinessException(ErrorCode.TUAN_CANNOT_USE);
            }
            if (StrUtil.isNotBlank(coupon.getTuanProcess()) && !coupon.getTuanProcess().equals(tuan.getTuanProcess())) {
                throw new BusinessException(ErrorCode.COUPON_TIME_CANNOT_USE);
            }
            if (coupon.getNeedPrice() > totalPrice) {
                throw new BusinessException(ErrorCode.COUPON_CONDITION_CANNOT_USE);
            }
            couponPrice = coupon.getCouponPrice();
        }
        totalPrice -= couponPrice;
        //1.订单生成
        String outTradeNo = customFormatDate("yyyyMMddHHmmssSSSSSSS");
        Orders orders = new Orders();
        BeanUtils.copyProperties(detail, orders);


        User user = userMapper.selectById(userId);
        orders.setMerchantId(merchantId);
        orders.setProductId(productId);
        orders.setProductItemId(productItemId);
        orders.setProductItemSize(userTuan.getProductItemSize());
        orders.setOutTradeNo(outTradeNo);
        orders.setUserId(Integer.valueOf(userId));
        orders.setUnitPrice(uniPrice);
        orders.setPostFee(postFee);
        orders.setTotalPrice(totalPrice);
        orders.setUserTuanId(detail.getUserTuanId());
        orders.setTuanName(tuan.getTuanName());
        orders.setTuanProcess(tuan.getTuanProcess());
        orders.setOrderStatus(OrderStatus.WEIFUKUAN);
        Integer totalFee = Double.valueOf(totalPrice * 100).intValue();
        ordersMapper.insert(orders);
        //2. JSAPI微信统一下单
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
        wxPayUnifiedOrderRequest.setOutTradeNo(outTradeNo);
        wxPayUnifiedOrderRequest.setTotalFee(totalFee);
        wxPayUnifiedOrderRequest.setSpbillCreateIp("123.12.12.2");
        wxPayUnifiedOrderRequest.setNotifyUrl("https://www.nb.cn:8080/v1/wx/notify");
        wxPayUnifiedOrderRequest.setTradeType("JSAPI");
        wxPayUnifiedOrderRequest.setBody(product.getProductName() + " " + productItem.getItemName());
        wxPayUnifiedOrderRequest.setOpenid(user.getOpenId());
        wxPayUnifiedOrderRequest.setAppid(appId);
        WxPayUnifiedOrderResult wxPayUnifiedOrderResult = wxService.unifiedOrder(wxPayUnifiedOrderRequest);
        System.out.println(wxPayUnifiedOrderResult.getPrepayId());
        String prepayId = wxPayUnifiedOrderResult.getPrepayId();


        //3. 生成小程序调起支付所需的数据
        WxPayment wxPayment = new WxPayment();
        wxPayment.setWxTradeId(outTradeNo);
        wxPayment.setAppId(appId);
        wxPayment.setTimeStamp((System.currentTimeMillis() / 1000) + "");
        wxPayment.set_package("prepay_id=" + wxPayUnifiedOrderResult.getPrepayId());
        wxPayment.setNonceStr(IdUtil.fastSimpleUUID());
        wxPayment.setSignType("MD5");
        wxPayment.sign(mchKey);
        return ResponseApi.success(wxPayment);
    }

    @Override
    public ResponseApi<Object> queryWxOrder(String outTradeNo, HttpServletRequest request) {
        String userId = JWT.getTokenId(request.getHeader("token"));
        User user = userMapper.selectById(userId);
        try {

            WxPayOrderQueryResult wxPayOrderQueryResult = wxService.queryOrder(null, outTradeNo);
            System.out.println(wxPayOrderQueryResult.toString());
            if (wxPayOrderQueryResult.getTradeState().equals("NOTPAY")) {

                throw new BusinessException(ErrorCode.NON_PAYMENT);
            }
            Orders order = ordersMapper.getOrderByOutTradeNo(outTradeNo);
            order.setOrderStatus(OrderStatus.YIFUKUAN);
            order.setPaymentTime(LocalDateTime.now().toString());
            UserTuan userTuan = userTuanMapper.selectById(order.getUserTuanId());
            if (order.getTuanProcess().equals(TuanProcess.YIXIANGJIN)) {
                userTuan.setTuanProcess(TuanProcess.YIXIANGJIN);
                userTuan.setProcessNo(0);
                userTuan.setNextTuanProcess(TuanProcess.DINGJIN);
                userTuan.setBuyerRate(0);
                userTuan.setYixiangjinOrderId(order.getOrderId());
                userTuan.setYixiangjinCreateTime(order.getCreateTime());
                userTuan.setYixiangjinOutTradeNo(outTradeNo);
                int insert = userTuanMapper.insert(userTuan);
                order.setUserTuanId(insert);
            } else if (order.getTuanProcess().equals(TuanProcess.DINGJIN)) {
                userTuan.setProcessNo(1);
                userTuan.setTuanProcess(TuanProcess.DINGJIN);
                userTuan.setNextTuanProcess(TuanProcess.WEIKUAN);
                userTuan.setDingjinOrderId(order.getOrderId());
                userTuan.setDingjinCreateTime(order.getCreateTime());
                userTuan.setDingjinOutTradeNo(outTradeNo);
            } else {
                userTuan.setProcessNo(2);
                userTuan.setTuanProcess(TuanProcess.WEIKUAN);
                userTuan.setNextTuanProcess(TuanProcess.END);
                userTuan.setWeikuanOrderId(order.getOrderId());
                userTuan.setWeikuanCreateTime(order.getCreateTime());
                userTuan.setWeikuanOutTradeNo(outTradeNo);
            }
            ordersMapper.updateById(order);
            List<Coupon> coupons = couponMapper.selectList(new QueryWrapper<Coupon>().eq("is_online", 1).eq("product_id", order.getProductId()).lt("need_price", order.getTotalPrice()).eq("trigger_tuan_process", order.getTuanProcess()));
            coupons.forEach(item -> {
                UserCoupon userCoupon = new UserCoupon();
                userCoupon.setCouponId(item.getCouponId());
                userCoupon.setUserId(user.getUserId());
                userCoupon.setIsUsed(0);
                userCouponMapper.insert(userCoupon);
            });
        } catch (Exception e) {
            e.printStackTrace();
            //异常，订单不存在
        }
        return ResponseApi.success();


    }


}




